import * as OSS from 'ali-oss';
import * as path from 'path';
import { ConfigService } from '@nestjs/config';
import { Injectable, OnModuleInit } from '@nestjs/common';

export enum OSSDispositionEnum {
  Attachment = 'attachment; filename="example.txt"',
  Inline = 'inline',
}

export enum OSSObjectAclEnum {
  Private = 'private',
  PublicRead = 'public-read',
}

export enum OSSTagEnum {
  Tag1 = 'Tag1=1',
  Tag2 = 'Tag2=2',
}

// 创建一个可注入的OSS服务，这样可以确保环境变量已加载
@Injectable()
export class OSSService implements OnModuleInit {
  private client: OSS;

  constructor(private configService: ConfigService) {}

  onModuleInit() {
    this.client = new OSS({
      // yourregion填写Bucket所在地域。以华东1（杭州）为例，Region填写为oss-cn-hangzhou。
      region: 'oss-cn-chengdu',
      // 使用ConfigService获取环境变量
      accessKeyId: this.configService.get<string>('OSS_ACCESS_KEY_ID'),
      accessKeySecret: this.configService.get<string>('OSS_ACCESS_KEY_SECRET'),
      authorizationV4: true,
      // 填写Bucket名称。
      bucket: 'hero-oss',
    });
  }

  getClient() {
    return this.client;
  }
}

// 导出一个函数，用于在非注入环境中获取配置（如需要）
export function getOSSConfig() {
  // 确保dotenv已加载
  if (!process.env.OSS_ACCESS_KEY_ID) {
    const { config } = require('dotenv');
    config({ path: '.env' });
  }
  
  return {
    region: 'oss-cn-chengdu',
    accessKeyId: process.env.OSS_ACCESS_KEY_ID,
    accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
    authorizationV4: true,
    bucket: 'hero-oss',
  };
}

// 创建一个可以直接使用的客户端实例
let client: OSS;
function getClient() {
  if (!client) {
    const config = getOSSConfig();
    client = new OSS(config);
  }
  return client;
}

// 自定义请求头
const headers = {
  // 指定Object的存储类型。
  'x-oss-storage-class': 'Standard',
  'Content-Disposition': OSSDispositionEnum.Inline,
  // 指定Object的标签，可同时设置多个标签。
  'x-oss-tagging': OSSTagEnum.Tag1,
  // 指定PutObject操作时是否覆盖同名目标Object。此处设置为true，表示禁止覆盖同名Object。
  'x-oss-forbid-overwrite': 'false',
  // 移除手动设置的Authorization和公共访问权限，让OSS客户端自动处理
};

export async function ossPut (objectName: string) {
  try {
    // 使用上面的getClient函数获取客户端实例
    const client = getClient();
    
    // 填写OSS文件完整路径和本地文件的完整路径。OSS文件完整路径中不能包含Bucket名称。
    // 如果本地文件的完整路径中未指定本地路径，则默认从示例程序所属项目对应本地路径中上传文件。
    const result = await client.put(
      objectName,
      path.normalize(path.resolve(__dirname, '../public/uploads/' + objectName)),
      {headers}
    );
    
    return result;
  } catch (e) {
    console.log(e);
  }
}

// 获取带有签名的临时访问URL
export async function getSignedUrl(objectName: string, expires = 3600) {
  const client = getClient();
  return await client.signatureUrl(objectName, {
    expires: expires, // URL有效期，单位为秒
    method: 'GET', // 请求方法
  });
}
